本文转自:掘金 - RunTitan - Flutter之可滑动Widget
还有一些自己的理解
在 Android 中,如果控件超出了显示范围,会只显示一部分,而在 Flutter
中, 当内容超过显示视图时,如果没有特殊处理,Flutter
则会提示 Overflow
错误。
Flutter
提供了多种可滚动(Scrollable Widget
)用于显示列表和长布局。
可滚动 Widget
都直接或间接包含一个 Scrollable
, 下面是常用的几个可滚动的 Widget
SingleChildScrollView
ListView
GridView
CustomScrollView
- 滚动监听及控制
ScrollController
Scrollbar
Scrollbar
是一个 Material
风格的滚动指示器(滚动条),如果要给可滚动 widget
添加滚动条,只需将 Scrollbar
作为可滚动 widget
的父 widget
即可
CupertinoScrollbar
是iOS
风格的滚动条,如果你使用的是Scrollbar
,那么在iOS
平台它会自动切换为CupertinoScrollbar
Scrollbar
和CupertinoScrollbar
都是通过ScrollController
来监听滚动事件来确定滚动条位置,关于ScrollController
详细的内容我们将在后面专门一节介绍- 下面是
Scrollbar
和CupertinoScrollbar
的构造函数, 都只有一个child
属性, 用于接受一个可滚动的Widget
const Scrollbar({
Key key,
@required this.child,
})
const CupertinoScrollbar({
Key key,
@required this.child,
})
示例:
body: Scrollbar(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
Center(child: Image.asset("assets/images/icon_2.png"),),
],
),
),
)
效果如下,注意屏幕右侧的滚动条:
SingleChildScrollView
SingleChildScrollView
类似于 Android 中的 ScrollView
, 不再详细介绍了, 下面看一下具体使用介绍吧:
const SingleChildScrollView({
Key key,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.padding,
bool primary,
this.physics,
this.controller,
this.child,
})
scrollDirection,设置视图的滚动方向(默认垂直方向), 需要对应的设置其子
Widget
是Column
或者Row
, 否则会报Overflow
错误。reverse,是否按照阅读方向相反的方向滑动
- 若
reverse: false
,则滚动内容头部和左侧对其, 那么滑动方向就是从左向右 - 若
reverse: true
,则滚动内容尾部和右侧对其, 那么滑动方向就是从右往左。
- 若
padding,内边距
primary,是否使用默认的 controller
physics,此属性接受一个
ScrollPhysics
对象,它决定可滚动Widget
如何响应用户操作,比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。默认情况下,
Flutter
会根据具体平台分别使用不同的ScrollPhysics
对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在iOS
上会出现弹性效果,而在Android
上会出现微光效果。如果你想在所有平台下使用同一种效果,可以显式指定,
Flutter SDK
中包含了两个ScrollPhysics
的子类可以直接使用:ClampingScrollPhysics
:安卓下微光效果。BouncingScrollPhysics
:iOS
下弹性效果。
controller,此属性接受一个
ScrollController
对象,ScrollController
的主要作用是控制滚动位置和监听滚动事件。默认情况下,
widget
中会有一个默认的PrimaryScrollController
,如果子widget
中的可滚动widget
没有显式的指定controller
并且primary
属性值为true
时(默认就为true
),可滚动widget
会使用这个默认的PrimaryScrollController
,这种机制带来的好处是父widget
可以控制子树中可滚动widget
的滚动,例如,Scaffold
使用这种机制在iOS
中实现了"回到顶部"的手势。child,子控件。
示例:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({
Key key,
}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SingleChildScrollView Demo'),
),
body: Theme.of(context).platform == TargetPlatform.iOS
? CupertinoScrollbar(
child: _buildListView(),
)
: Scrollbar(
child: _buildListView(),
),
);
}
Padding _buildListView() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Column(children: generatorLists(30)),
),
);
}
}
List<Widget> generatorLists(n) {
List<Widget> lst = [];
for (var i = 0; i < n; i++) {
lst.add(Container(
decoration: BoxDecoration(color: Colors.cyanAccent),
width: double.infinity,
height: 30,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("${i}"),
));
}
return lst;
}
效果如下: